﻿#include "ZRingBuffer.h"

#include <algorithm>
#include <cstring>
#include <iostream>
#include <ostream>
#include <stdexcept>

ZRingBuffer::ZRingBuffer(const ZRingBuffer &other) {
  // 复制其他对象的内容
  container_ = other.container_;
  buffer_ = container_.data();
  capacity_ = other.capacity_;
  head_ = other.head_;
  tail_ = other.tail_;
  count_ = other.count_;
  externalBuffer_ = other.externalBuffer_;
}

ZRingBuffer::ZRingBuffer(ZRingBuffer &&other) noexcept {
  // 移动其他对象的内容
  container_ = std::move(other.container_);
  buffer_ = container_.data();
  capacity_ = other.capacity_;
  head_ = other.head_;
  tail_ = other.tail_;
  count_ = other.count_;
  externalBuffer_ = other.externalBuffer_;
}

ZRingBuffer::ZRingBuffer(size_t size)
    : container_(std::vector<uint8_t>(size)),
      buffer_(container_.data()),
      capacity_(size) {
  int a = 0;
}

ZRingBuffer::ZRingBuffer(void *data, size_t size)
    : buffer_(static_cast<uint8_t *>(data)),
      capacity_(size),
      externalBuffer_(true) {
}

ZRingBuffer::~ZRingBuffer() {
}

size_t ZRingBuffer::size() const {
  return count_;
}

size_t ZRingBuffer::capacity() const {
  return capacity_;
}

uint8_t *ZRingBuffer::data() {
  // 当前的数据开头的指针
  return buffer_ + head_;
}

ZRingBuffer ZRingBuffer::linearData() {
  // 没有数据则返回个空的
  if (count_ == 0) {
    return {};
  }

  // 初始化一个线性缓冲区
  ZRingBuffer linearBuffer(count_);
  // 如果数据是线性的,则直接复制
  if (head_ + count_ <= capacity_) {
    std::memcpy(linearBuffer.buffer_, buffer_ + head_, count_);
  } else {
    // 数据是环形的,需要分两次复制
    size_t firstPart = capacity_ - head_;
    // 复制第一部分
    std::memcpy(linearBuffer.buffer_, buffer_ + head_, firstPart);
    // 复制第二部分
    std::memcpy(linearBuffer.buffer_ + firstPart, buffer_, count_ - firstPart);
  }
  // 设置线性缓冲区的尾部指针
  linearBuffer.tail_ = 0;
  linearBuffer.count_ = count_;
  return linearBuffer;
}

void ZRingBuffer::clean() {
  head_ = 0;
  tail_ = 0;
  count_ = 0;
}

void ZRingBuffer::resize(size_t size) {
  // 如果是外部缓冲区,则不能调整大小
  if (externalBuffer_) {
    std::cerr << "Cannot resize external buffer_" << std::endl;
    throw std::runtime_error("Cannot resize external buffer_");
  }

  // 如果大小没有变化,则不处理
  if (size == capacity_) {
    clean();
    return;
  }

  // 分配新的缓冲区
  container_.resize(size);
  // 设置新的缓冲区和相关参数
  buffer_ = container_.data();
  capacity_ = size;
  head_ = 0;
  tail_ = 0;
  count_ = 0;
}

uint8_t ZRingBuffer::at(size_t pos) {
  // 使用重载的[]操作符,返回值是复制的
  return (*this)[pos];
}

uint8_t &ZRingBuffer::operator[](size_t pos) {
  // 检查索引是否越界
  if (pos >= count_) {
    std::cerr << "Out of bounds access" << std::endl;
    throw std::out_of_range("Index out of range");
  }
  // 计算实际的索引位置并返回引用
  return buffer_[(head_ + pos) % capacity_];
}

void ZRingBuffer::push_front(uint8_t value) {
  // 如果缓冲区已满,则抛出异常
  if (count_ == capacity_) {
    std::cerr << "Buffer is full" << std::endl;
    throw std::runtime_error("Buffer is full");
  }
  head_ = (head_ - 1 + capacity_) % capacity_;
  buffer_[head_] = value;
  ++count_;
}

void ZRingBuffer::push_front(void *data, size_t size) {
  // 数据大小为0时,不需要处理
  if (size == 0) {
    return;
  }

  // 检查缓冲区是否有足够的空间
  if (count_ + size > capacity_) {
    throw std::runtime_error("Not enough space in buffer_");
  }

  // 转化数据指针
  auto src = static_cast<uint8_t *>(data);

  // 移动head指针，为新数据腾出空间
  head_ = (head_ - size + capacity_) % capacity_;

  // 分两种情况复制数据：
  if (head_ + size <= capacity_) {
    // 1. 新数据可以连续存放
    std::memcpy(buffer_ + head_, src, size);
  } else {
    // 2. 新数据需要分成两部分存放（环绕缓冲区末尾）
    size_t firstPart = capacity_ - head_;
    std::memcpy(buffer_ + head_, src, firstPart);
    std::memcpy(buffer_, src + firstPart, size - firstPart);
  }

  count_ += size;
}

void ZRingBuffer::push_back(uint8_t value) {
  if (count_ == capacity_) {
    std::cerr << "Buffer is full" << std::endl;
    throw std::runtime_error("Buffer is full");
  }
  // 如果尾部指针已经到达容量,则需要处理环形缓冲区的情况
  buffer_[tail_] = value;
  ++tail_;
  if (tail_ >= capacity_) {
    // 如果尾部指针超过了容量,则需要环绕到开头
    tail_ = 0;
  }
  ++count_;
}

void ZRingBuffer::push_back(void *data, size_t size) {
  // 数据大小为0时,不需要处理
  if (size == 0) {
    return;
  }

  // 检查缓冲区是否有足够的空间
  if (count_ + size > capacity_) {
    throw std::runtime_error("Not enough space in buffer_");
  }

  // 转化数据指针
  auto *src = static_cast<uint8_t *>(data);

  // 分两种情况复制数据：
  if (tail_ + size <= capacity_) {
    // 1. 新数据可以连续存放
    std::memcpy(buffer_ + tail_, src, size);
  } else {
    // 2. 新数据需要分成两部分存放（环绕缓冲区末尾）
    size_t firstPart = capacity_ - tail_;
    std::memcpy(buffer_ + tail_, src, firstPart);
    std::memcpy(buffer_, src + firstPart, size - firstPart);
  }
  tail_ = (tail_ + size) % capacity_;

  count_ += size;
}

void ZRingBuffer::pop_front(size_t size) {
  if (count_ < size) {
    this->clean();
  } else {
    head_ = (head_ + size) % capacity_;
    count_ -= size;
  }
}

void ZRingBuffer::pop_back(size_t size) {
  if (count_ < size) {
    this->clean();
  } else {
    tail_ = (tail_ - size + capacity_) % capacity_;
    count_ -= size;
  }
}

ZRingBuffer ZRingBuffer::left(size_t size) {
  return mid(0, static_cast<int>(size));
}

void ZRingBuffer::left(size_t size, void *data) {
  // 检查请求的大小是否超过当前元素数量
  if (size > count_) {
    // 复制所有的数据
    size = count_;
  }

  // 检查数据指针是否为nullptr
  if (data == nullptr) {
    std::cerr << "Data pointer is null" << std::endl;
    throw std::runtime_error("Data pointer is null");
  }

  // 转化数据指针
  auto dest = static_cast<uint8_t *>(data);
  // 如果请求的大小小于等于当前元素数量,则复制数据
  for (size_t i = 0; i < size; ++i) {
    dest[i] = (*this)[i];
  }
}

ZRingBuffer ZRingBuffer::right(size_t size) {
  // 如果请求的大小大于等于当前元素数量,则返回从头到尾的所有元素
  if (size >= count_) {
    return mid(0, -1);
  }
  return mid(static_cast<int>(count_ - size), -1);
}

ZRingBuffer ZRingBuffer::mid(int pos, int len) {
  // 检查位置和长度的有效性
  if (count_ == 0 || pos < 0 || pos >= count_) {
    return {};
  }

  // 如果长度为-1或者超过了剩余长度,则表示到buffer的末尾
  if (len == -1 || static_cast<size_t>(pos + len) > count_) {
    len = static_cast<int>(count_ - pos);
  }

  // 创建一个新的ZRingBuffer对象来存储结果
  ZRingBuffer result(len);
  for (int i = 0; i < len; ++i) {
    result.push_back((*this)[pos + i]);
  }
  return std::move(result);
}

int ZRingBuffer::indexOf(uint8_t value, int startPos) {
  // 检查起始位置的有效性
  if (startPos < 0 || startPos >= count_) {
    return -1;
  }

  for (auto i = startPos; i < count_; ++i) {
    if ((*this)[i] == value) {
      return i;
    }
  }
  return -1;
}

int ZRingBuffer::indexOf(void *data, size_t size, int startPos) {
  // 检查起始位置和大小的有效性
  if (startPos < 0 || startPos >= count_ || size == 0 || size > count_) {
    return -1;
  }

  // 转化数据指针
  auto target = static_cast<uint8_t *>(data);
  for (auto i = startPos; i <= count_ - size; ++i) {
    // 检查从当前位置开始的size个元素是否与目标数据匹配
    // 使用一个标志变量来判断是否匹配
    bool match = true;
    // 遍历size个目标元素
    for (size_t j = 0; j < size; ++j) {
      // 检查当前元素是否与目标数据匹配
      if ((*this)[i + j] != target[j]) {
        // 如果不匹配,则设置标志为false并跳出循环
        match = false;
        break;
      }
    }
    // 如果匹配成功,则返回当前索引
    if (match) {
      return i;
    }
  }
  // 如果没有找到匹配的元素,则返回-1
  return -1;
}

void ZRingBuffer::print() {
  std::cout << "ZRingBuffer: size=" << count_ << ", capacity_=" << capacity_
            << ", head_=" << head_ << ", tail_=" << tail_ << std::endl;
  std::cout << "Data: ";
  for (size_t i = 0; i < count_; ++i) {
    std::cout << static_cast<int>((*this)[i]) << " ";
  }
  std::cout << std::endl;
}
